package asteroids.model.statements;

import java.util.*;

import asteroids.model.*;
import asteroids.model.expressions.E;
import asteroids.model.types.*;

/**
 * A class that represents a sequence of statements
 * 
 * @version 1.0
 * 
 * @author	Thijs Peirelinck & Wouter Parys
 *
 */
public class Sequence implements NormalS {
	
	private List<S> statements;
	
	public Sequence(List<S> statements) {
		this.statements = statements;
	}
	
	public List<S> getStatements() {
		return statements;
	}
	
	@Override
	public void setExecuter(Ship executer) {
		for(int i = 0; i < statements.size(); i++) {
			statements.get(i).setExecuter(executer);
		}
	}
	
	@Override
	public Iterator<S> iterator(final HashMap<String, E> variables) {
		return new Iterator<S>() {
			
			{
			if (getStatements().size() != 0) {
				if (getStatements().get(0) instanceof NormalS) {
					currentIterator = ((NormalS)statements.get(0)).iterator(variables);
					iteratorInitialized = true;
				}
			}
			}

			private int counter;
			private boolean iteratorInitialized;
			private Iterator<S> currentIterator;
			
			@Override
			public boolean hasNext() {
				if (statements.size() != 0 && counter < statements.size()) {
					if (iteratorInitialized) {
						if (currentIterator.hasNext()){
							return true;
						}							
						if (counter < (statements.size()-1) && !currentIterator.hasNext()) {
							if (statements.get(counter + 1) instanceof NormalS) {
								return ((NormalS)statements.get(counter+1)).iterator(variables).hasNext(); }
							else {
								return true; }
						}
						return false;
					}
					return true;
				}
				return false;
			}

			@Override
			public S next() throws NoSuchElementException {
				if(!hasNext()) 
					throw new NoSuchElementException();
				if (!(statements.get(counter) instanceof NormalS)) {
					counter++;
					currentIterator = ((NormalS)statements.get(counter)).iterator(variables);
					iteratorInitialized = true;
					return statements.get(counter-1);
				}
				else {
					if (!currentIterator.hasNext()) {
						counter++;
						if (counter < statements.size()) {
							currentIterator = ((NormalS)statements.get(counter)).iterator(variables);
						}
					}							
					return currentIterator.next();
				}
			}

			@Override
			public void remove() throws UnsupportedOperationException {
				throw new UnsupportedOperationException();
			}
			
		};
		
	}
	
	@Override
	public boolean typeCheck(Map<String, T> globals) {
		for(int i = 0; i < statements.size(); i++) {
			if(!statements.get(i).typeCheck(globals))
				return false;
		}
		return true;
	}
	
	@Override
	public boolean containsAction() {
		for(int i = 0; i < statements.size(); i++) {
			S s = statements.get(i);
			if(s instanceof NormalS) {
				if(((NormalS)s).containsAction())
					return true;
			}
			if(s instanceof Action)
				return true;
		}
		return false;
	}
	
	
}
